/*
# mem.c - низкоуровневый менеджер памяти
#
# fetch (zfetch@mail.ru)
#
#
#
*/
#include <types.h>
#include "fmem.h"


//Возвращает объем физической памяти в мегабайтах
uint32 avail_memory()
{
	uint8 *mem = (uint8 *) 0x400000;
	uint32 msize = 4;
	do{
		mem += MB;
		*mem = 0xF;
		msize++;
	}while(*mem == 0xF);
	return msize;
}

//Возвращает количество кадров в памяти (кадр=4kb=4096=0x1000)
uint32 avail_frames()
{
	return avail_memory() * MB / 0x1000;
}

/*Инициализация менеджера кадров
	1. Вычислить, сколько кадров можно разместить в памяти
	2. Пометить все не зарезервированные кадры как свободные
*/
void init_framem(){
	uint32 i = 0, reserv = 100, j = 0;
	mfsize = avail_frames() / 8;//За каждый шаг покрываем 8 "кадров"
	//kprintf("mfsize: %X, reserv: %X\n", mfsize, reserv);
	while(i <= mfsize){
		if(i < reserv){ 
			fbmap[i] = 0xFF;
			//kprintf("+"); 
		}else{ 
			fbmap[i] = 0; 
			//kprintf("-");
			j++;
		}
		i++;
	}
	//puts("\n");
	//for(i = 0; i <= mfsize; i++){
	//	fbmap[i] = 0;
	//}
	//for(i = 0; i <= mfsize; i++){
	//	fbmap[mfsize - 2] = 0x0;
	//	fbmap[mfsize - 1] = 0x0;
	//	fbmap[mfsize] = 0x0;
	//	kprintf("%X", fbmap[i]);
	//}
	//puts("\n");
	//kprintf("Size: %X, free: %X\n", mfsize, j);
}

/*Занять один кадр 
	1. Пометить в карте, что кадр занят
	2. Вернуть адрес кадра в физической памяти
*/
uint32 * alloc_frame()
{
	uint32 i = 0, z = 0, addr;
	kprintf("ALLOC_FRAME\n")
	while(i < mfsize){
		kprintf("mfsize: %X, i: %X\n", fbmap[i], i);
		if(fbmap[i] < 0xff){
			kprintf("\ngood\n");
			while(z < 8){
				if(((fbmap[i] >> z) & 0x1) == 0){
					fbmap[i] |= (0x1 << z);
					addr = (i * 8 + z) * 4096;
					return (unsigned int *)addr;
				} 
				z++;
			}
		}
		i++;
	}
	
	kprintf("%i\n", i);
	kprintf("Where is SWAP\n");
	for(;;){};
	
}
//Освободить кадр (пометить в карте, что кадр свободен)
void free_frame(uint32 *addr){
	uint32 i, z, map_entr = (uint32)addr / 4096;
	//kprintf("K%x\n",map_entr);
	i = map_entr / 8;
	//kprintf("I%i\n",i);
	z = map_entr % 8;
	//kprintf("Z%i\n",z);
	fbmap[i] &= ~(0x1 << z);	
}


inline int
memcp(void *src, void *dst, uint32 sz){
	asm("movl %0, %%esi"::"r" ((uint32)src):"%eax");
	asm("movl %0, %%edi"::"r" ((uint32)dst):"%eax");
	asm("movl %0, %%ecx"::"r" (sz):"%eax");
	asm("rep movsb;");
}


